package modelo.Tests;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import modelo.AlgoHero.*;
import modelo.Excepciones.*;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import junit.framework.TestCase;

public class PartituraTest extends TestCase {
	
	private NotaTest testNota;
	
	public PartituraTest (){
		testNota = new NotaTest();
	}
	
	/**
	 * Metodo que devuelve un partitura creada con 3 notas:
	 * FA  BLANCA
	 * SOL NEGRA
	 * SOL NEGRA
	 * @return
	 */
	public Partitura getPartitura1 (){
		
		Duracion.setDuracion(Figura.REDONDA,1);
		
		Partitura partitura = new Partitura ();
		
		try{
		partitura.add(testNota.getFaBLANCA());
		partitura.add(testNota.getsolNEGRA());
		partitura.add(testNota.getsolNEGRA());
		}catch (EspacioNoSuficienteEnPartitura e){
			
			System.err.println("Partitura sin espacio suficiente");
						
		}
		
		return partitura;
	}
	
	
	public PartituraTraducida getPartituraTraducida1 (){
		
		PartituraTraducida partituraTraducidaAux = new PartituraTraducida();
		
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.INICIAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.FINAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.INICIAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.FINAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.INICIAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.FINAL));
		
		return partituraTraducidaAux;
	}
	
	/**
	 * Metodo que devuelve una partitura creada con 2 notas:
	 * FA	BLANCA
	 * FA	BLANCA
	 * @return
	 */
	public Partitura getPartitura2 (){
		
		Duracion.setDuracion(Figura.REDONDA,1);
		
		Partitura partitura = new Partitura ();
		
		try{
		partitura.add(this.testNota.getFaBLANCA());
		partitura.add(this.testNota.getFaBLANCA());
		}catch (EspacioNoSuficienteEnPartitura e){
			
			System.err.println("Partitura sin espacio suficiente");
		}
		
		return partitura;
	}
	
	public PartituraTraducida getPartituraTraducida2 (){
		
		PartituraTraducida partituraTraducidaAux = new PartituraTraducida();
		
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.INICIAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.FINAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.INICIAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.FINAL));
	
		return partituraTraducidaAux;
	}
	

	/**
	 * Metodo que crea un nodo con lo de partitura
	 */
	public Element crearNodo() throws ParserConfigurationException
	{
		  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		  DocumentBuilder db = dbf.newDocumentBuilder(); 
	   	  Document doc = db.newDocument();
	   	  Element elemento = doc.createElement("partitura");	
	   	  Element elementoHijo = doc.createElement("nota");	   	  
	   	  elementoHijo.setAttribute("figura", "CORCHEA");
	   	  elementoHijo.setTextContent("SOL");
	   	  elemento.appendChild(elementoHijo);	   	  
	   	  return elemento;	  
	}
	
	
	/**
	 * Metodo que intenta crear una partitura con notas que exeden la longitud de compas
	 * @return
	 */
	
	public Partitura getPartitura3 (){
		
		Duracion.setDuracion(Figura.REDONDA,1);
		
		Partitura partitura = new Partitura ();
		
		try{
		partitura.add(this.testNota.getFaBLANCA());
		partitura.add(this.testNota.getFaBLANCA());
		partitura.add(this.testNota.getsiSEMICORCHEA());
		}catch (EspacioNoSuficienteEnPartitura e){
			
			System.err.println("Partitura sin espacio suficiente");
			assertTrue(true);
		
		}
		return partitura;
		
	}
	/**
	 * Metodo que devuelve una partitura creada con 2 notas:
	 * FA	BLANCA
	 * FA	BLANCA
	 * @return
	 */
	public Partitura getPartitura4 (){
		
		Duracion.setDuracion(Figura.BLANCA,1);
		
		Partitura partitura = new Partitura ();
		
		try{
		partitura.add(this.testNota.getsolNEGRA());
		partitura.add(this.testNota.getDoSILENCIODENEGRA());
		}catch (EspacioNoSuficienteEnPartitura e){
			
			System.err.println("Partitura sin espacio suficiente");
		}
		
		return partitura;
	}
	
	public PartituraTraducida getPartituraTraducida4 (){
		
		PartituraTraducida partituraTraducidaAux = new PartituraTraducida();
		
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.INICIAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.MEDIO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.FINAL));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.NULO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.NULO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.NULO));
		partituraTraducidaAux.add(FactoryElementos.crearElemento(TipoElementoReproducible.NULO));

	
		return partituraTraducidaAux;
	}
	
	
	/**
	 * Metodo que verifica la comparacion de partituras Traducidas
	 */
	
	public void testComparacion (){
		
		PartituraTraducida partituraTraducida1;
		PartituraTraducida partituraTraducida2;
		PartituraTraducida partituraTraducida3;
		
		partituraTraducida1 = (PartituraTraducida) this.getPartitura1().traducir();
		partituraTraducida2 = (PartituraTraducida) this.getPartitura1().traducir();
		
		Boolean resultado = partituraTraducida1.compareTo(partituraTraducida2);
		
		assertTrue (resultado);
		
		partituraTraducida3 = (PartituraTraducida) this.getPartitura2().traducir();
		
		resultado = partituraTraducida3.compareTo(partituraTraducida1);
		
		assertFalse (resultado);
		
	}
	/**
	 * Metodo que verifica la correcta traduccion de una partitura
	 */
	public void testTraducirPartituraOK (){
		
		PartituraTraducida partituraTraducida;
		
		partituraTraducida = (PartituraTraducida) this.getPartitura1().traducir();
		
		assertTrue(this.getPartituraTraducida1().compareTo(partituraTraducida));
		
		partituraTraducida = (PartituraTraducida) this.getPartitura2().traducir();
		
		assertTrue(this.getPartituraTraducida2().compareTo(partituraTraducida));
		
		partituraTraducida = (PartituraTraducida) this.getPartitura4().traducir();
		
		assertTrue ( this.getPartituraTraducida4().compareTo(partituraTraducida));
		
	}
	
	/**
	 * Metodo que verifica que se lanze la exepcion correspodiente al crear una partitura de manera incorrecta
	 */
	public void testTraducirPartituraERR(){
		
		this.getPartitura3().traducir();
		
	}
	
	/**
	 * Metodo que verifica que se creen las notas mediante un nodo partitura
	 */
	
	public void testDeserialize () throws ParserConfigurationException{
		Element elemento = crearNodo();
		Partitura partitura = new Partitura();
		partitura.Deserialize(elemento);
		assertTrue(!(partitura.isEmpty()));
	}
	

}
